package com.cloudeasy.label.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudeasy.api.constant.AmqpConstant;
import com.cloudeasy.api.enums.ResultCodeEnum;
import com.cloudeasy.api.exception.CloudEasyException;
import com.cloudeasy.api.util.SnowFlake;
import com.cloudeasy.label.constant.LabelConstant;
import com.cloudeasy.label.dto.LabelDTO;
import com.cloudeasy.label.mapper.LabelMapper;
import com.cloudeasy.label.po.Label;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;

@Service
@Transactional(rollbackFor = Exception.class)
public class LabelService extends ServiceImpl<LabelMapper, Label> {

    private final LabelAttentionService labelAttentionService;

    private final AmqpTemplate amqpTemplate;

    private final SnowFlake snowFlake;

    public LabelService(@Lazy LabelAttentionService labelAttentionService, AmqpTemplate amqpTemplate, SnowFlake snowFlake) {
        this.labelAttentionService = labelAttentionService;
        this.amqpTemplate = amqpTemplate;
        this.snowFlake = snowFlake;
    }

    /**
     * 添加标签
     *
     * @param labelDTO {@link LabelDTO}
     * @return {@link Boolean}
     */
    public Boolean save(LabelDTO labelDTO) {
        if (existsName(labelDTO.getName())) {
            throw new CloudEasyException(ResultCodeEnum.NAME_EXISTS);
        }
        String id = String.valueOf(snowFlake.nextId());
        Label label = new Label();
        BeanUtils.copyProperties(labelDTO, label);
        label.setId(id);
        return this.save(label);
    }

    /**
     * 根据Id更新标签
     *
     * @param id       Id
     * @param labelDTO {@link LabelDTO}
     * @return {@link Boolean}
     */
    public Boolean updateById(String id, LabelDTO labelDTO) {
        Label label = this.getById(id);
        if (label == null) {
            throw new CloudEasyException(ResultCodeEnum.ID_NOT_EXISTS);
        }
        if (label.getStatus().equals(LabelConstant.FORBID_UPDATE)) {
            throw new CloudEasyException(ResultCodeEnum.FORBID_UPDATE);
        }
        if (!label.getName().equals(labelDTO.getName()) && existsName(labelDTO.getName())) {
            throw new CloudEasyException(ResultCodeEnum.NAME_EXISTS);
        }
        BeanUtils.copyProperties(labelDTO, label);
        return this.updateById(label);
    }

    /**
     * 根据Id删除标签
     *
     * @param id 标签Id
     * @return {@link Boolean}
     */
    public Boolean removeById(String id) {
        Label label = this.getById(id);
        if (label != null && label.getStatus().equals(LabelConstant.FORBID_DELETE)) {
            throw new CloudEasyException(ResultCodeEnum.FORBID_DELETE);
        }
        labelAttentionService.removeById(id);
        amqpTemplate.convertAndSend(AmqpConstant.LabelConstant.LABEL_REOMVE_ROUTING_KEY, id);
        return super.removeById(id);
    }

    /**
     * 判断名称是否存在
     *
     * @param name 名称
     * @return {@link Boolean}
     */
    private Boolean existsName(String name) {
        QueryWrapper<Label> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", name);
        return this.getOne(queryWrapper) != null;
    }

    /**
     * 添加关注
     *
     * @param labelId 标签Id
     */
    public void attention(String labelId) {
        this.attentionCountUpdate(labelId, 1);
    }

    /**
     * 取消关注
     *
     * @param labelId 标签Id
     */
    public void removeAttention(String labelId) {
        this.attentionCountUpdate(labelId, -1);
    }

    /**
     * 关注数量更新
     *
     * @param labelId 标签Id
     * @param inc     变化值
     */
    public void attentionCountUpdate(String labelId, int inc) {
        Label label = this.getById(labelId);
        if (label != null) {
            label.setAttentionCount(label.getAttentionCount() + inc);
        }
        this.updateById(label);
    }

    /**
     * 项数更新
     *
     * @param labelIds 标签Id列表
     * @param inc      自增值
     */
    public void itemIncByLabelIds(List<String> labelIds, Integer inc) {
        Collection<Label> labels = this.listByIds(labelIds);
        labels.forEach(label -> {
            label.setItemCount(label.getItemCount() + inc);
        });
        if (labels.size() == 0) {
            return;
        }
        this.updateBatchById(labels);
    }
}
